﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PojProject.Models;
using Algorithms;

namespace PojProject.Pojs
{
    public class Poj1753
    {
        ChessType[,] chessMapping;

        int MaxRow, MaxCol;

        public Poj1753(ChessType[,] chessMapping)
        {
            this.chessMapping = chessMapping;
            this.MaxRow = chessMapping.GetLength(0);
            this.MaxCol = chessMapping.GetLength(1);

            PintToConsole(chessMapping);
        }


        private void ChangeRelative(ChessType[,] chessMapping, int row, int col)
        {
            if (row + 1 < MaxRow)
                ReverseChess(chessMapping, row + 1, col);

            if (row - 1 >= 0)
                ReverseChess(chessMapping, row - 1, col);

            if (col + 1 < MaxCol)
                ReverseChess(chessMapping, row, col + 1);

            if (col - 1 >= 0)
                ReverseChess(chessMapping, row, col - 1);
        }

        private void ReverseChess(ChessType[,] chessMapping, int row, int col)
        {
            chessMapping[row, col] = chessMapping[row, col] == ChessType.whiteChess ? ChessType.BlackChess : ChessType.whiteChess;
        }

        private void PintToConsole(ChessType[,] chessMapping)
        {
            for (int i = 0; i < MaxRow; i++)
            {
                for (int j = 0; j < MaxCol; j++)
                {
                    var displayStr = chessMapping[i, j] == ChessType.whiteChess ? "W" : "B";
                    Console.Write(displayStr);
                }

                Console.WriteLine();
            }

            Console.WriteLine();
        }

        private List<int> RowColToMappingIndex()
        {
            List<int> ls = new List<int>();

            var m = MaxRow * MaxCol;

            for (int i = 0; i < m; i++)
            {
                ls.Add(i);
            }

            return ls;
        }

        private KeyValuePair<int, int> MappingIndexToRowCol(int mappingIndex)
        {
            int row = mappingIndex / MaxRow;
            int col = mappingIndex % MaxRow;

            return new KeyValuePair<int, int>(row, col);
        }

        private ChessType[,] CopyToChessMapping()
        {
            ChessType[,] copyMapping = new ChessType[MaxRow, MaxCol];

            for (int i = 0; i < MaxRow; i++)
            {
                for (int j = 0; j < MaxCol; j++)
                {
                    copyMapping[i, j] = chessMapping[i, j];
                }
            }

            return copyMapping;
        }

        public bool IsWin(ChessType[,] chessMapping, ChessType targetType)
        {
            for (int i = 0; i < MaxRow; i++)
            {
                for (int j = 0; j < MaxCol; j++)
                {
                    if (chessMapping[i, j] != targetType)
                    {
                        return false;
                    }
                }
            }

            return true;
        }

        public bool Play(ChessType targetChessType)
        {
            var mappingIndexes = RowColToMappingIndex();
            var al = new PermutationAndCombination<int>();
            for (int i = 1; i < MaxRow * MaxCol + 1; i++)
            {
                var co = al.GetCombination(mappingIndexes, i);

                foreach (var item in co)
                {
                    var copyMapping = CopyToChessMapping();

                    foreach (var index in item)
                    {
                        var rowCol = MappingIndexToRowCol(index);
                        ReverseChess(copyMapping, rowCol.Key, rowCol.Value);
                        ChangeRelative(copyMapping, rowCol.Key, rowCol.Value);
                    }

                    if (IsWin(copyMapping, targetChessType))
                    {
                        return true;
                    }
                }
            }

            return false;
        }
    }
}
